package com.rfid.AppNotifyImpl;

import com.rfid.reader.AppNotify;
import com.rfid.reader.MRfidReader;

import java.util.HashMap;
import java.util.Map;

public class MRfidReaderNotifyImpl implements AppNotify {
	private static final byte TLV_ONE_TAG_DATA = 0x50;
	private static final byte TLV_EPC = 0x01;
	private static final byte TLV_USER = 0x02;
	private static final byte TLV_TID = 0x04;
	private static final byte TLV_RSSI = 0x05;

	private static final int Message_Len_Start_Pos = 6;
	private static final int Message_Frame_Code_Pos = 5;
	private static final int Message_Attr_Start_Pos = 8;

	// �洢EPC���ݺ�����ӡʱ���ӳ��
	private Map<String, Long> epcLastPrintTimeMap = new HashMap<>();
	// ����5����
	private static final long PRINT_INTERVAL = 5000;

	public int GetTlvPosition(byte[] message, int startIndex, int paramLen, byte tlvType) {
		int pos = -1;
		int index = 0;
		for (index = 0; index < paramLen; index++) {
			if (message[startIndex] == tlvType) {
				pos = startIndex;
				break;
			} else {
				index = index + message[startIndex + 1] + 2;
				startIndex = startIndex + message[startIndex + 1] + 2;
			}
		}
		return pos;
	}

	@Override
	public int NotifyRecvTags(byte[] message, int startIndex) {
		int start_tlv_pos = startIndex + 8;
		int param_len = 0;
		int tag_tlv_pos = 0;
		int EPC_Tlv = 0;
		int index = 0;
		int interIndex = 0;
		int inter_tlv_pos = 0;
		int inter_tlv_len = 0;
		int inter_tlv = 0;

		param_len = message[startIndex + 6] & 0xFF;
		param_len = param_len << 8;
		param_len = message[startIndex + 7] & 0xFF;

//		System.out.print("From Reader[" + Integer.toHexString(message[startIndex + 3] & 0xFF) + " "
//				+ Integer.toHexString(message[startIndex + 4] & 0xFF) + "]:");

		while (index < param_len) {
			switch ((message[start_tlv_pos] & 0xFF)) {
				case TLV_ONE_TAG_DATA:
					// ����������ǩ����
					onTagRead();
					StringBuilder epcDataBuilder = new StringBuilder();
					boolean shouldPrint = true;

					// �Ƚ���EPC���������ж��Ƿ�Ӧ�ô�ӡ
					int tempInterIndex = 0;
					while (tempInterIndex < (message[start_tlv_pos + 1] & 0xFF)) {
						int tempInter_tlv_pos = start_tlv_pos + 2 + tempInterIndex;
						int tempInter_tlv = message[tempInter_tlv_pos] & 0xFF;
						int tempInter_tlv_len = message[tempInter_tlv_pos + 1] & 0xFF;

						if (tempInter_tlv == TLV_EPC) {
							for (int iIndex = 0; iIndex < tempInter_tlv_len; iIndex++) {
								epcDataBuilder.append(String.format("%02X", message[tempInter_tlv_pos + 2 + iIndex]));
							}
							break;
						}
						tempInterIndex += tempInter_tlv_len + 2;
					}

					String epcData = epcDataBuilder.toString();
					long currentTime = System.currentTimeMillis();
					Long lastPrintTime = epcLastPrintTimeMap.get(epcData);

					// ����Ƿ���5�����Ѿ���ӡ����ͬEPC������
					if (lastPrintTime != null && (currentTime - lastPrintTime) < PRINT_INTERVAL) {
						shouldPrint = false;
					}

					if (shouldPrint) {
						// ���¸�EPC������ӡʱ��
						epcLastPrintTimeMap.put(epcData, currentTime);

						// ��ӡ��ǩ����
						while (interIndex < (message[start_tlv_pos + 1] & 0xFF)) {
							inter_tlv_pos = start_tlv_pos + 2 + interIndex;
							inter_tlv = message[inter_tlv_pos] & 0xFF;
							inter_tlv_len = message[inter_tlv_pos + 1] & 0xFF;

							switch (inter_tlv) {
								case TLV_EPC:
									System.out.print("  EPC Data:");
									for (int iIndex = 0; iIndex < inter_tlv_len; iIndex++) {
										System.out.print(String.format("%02X", message[inter_tlv_pos + 2 + iIndex]));
									}
									break;
								case TLV_USER:
									System.out.print("  User Data:");
									for (int iIndex = 0; iIndex < inter_tlv_len; iIndex++) {
										System.out.print(String.format("%02X ", message[inter_tlv_pos + 2 + iIndex]));
									}
									break;
								case TLV_TID:
									System.out.print("  TID Data:");
									for (int iIndex = 0; iIndex < inter_tlv_len; iIndex++) {
										System.out.print(String.format("%02X ", message[inter_tlv_pos + 2 + iIndex]));
									}
									break;
								case TLV_RSSI:
									System.out.print(String.format(" RSSI:%02X ", message[inter_tlv_pos + 2]));
									break;
							}
							interIndex += inter_tlv_len + 2;
						}
						System.out.println();
					}
					break;
			}
			index += (message[start_tlv_pos + 1] & 0xFF) + 2;
			start_tlv_pos += (message[start_tlv_pos + 1] & 0xFF) + 2;
		}
		return 0;
	}

	private void onTagRead() {
		System.out.println("RFID");
	}

	
	@Override
	public int NotifyStartInventory(byte[] message, int startIndex) {
		return 0;
	}

	@Override
	public int NotifyStopInventory(byte[] message, int startIndex) {
		System.out.println("the reader stop reading.");
		return 0;
	}

	@Override
	public int NotifyReset(byte[] message, int startIndex) {
		int start_tlv_pos = startIndex + 8;
		int param_len = 0;
		int tag_tlv_pos = 0;
		int EPC_Tlv = 0;

		param_len = message[startIndex + 6] & 0xFF;
		param_len = param_len << 8;
		param_len = message[startIndex + 7] & 0xFF;

		tag_tlv_pos = GetTlvPosition(message, start_tlv_pos, param_len, MRfidReader.eTlvAttrStatus);
		if (tag_tlv_pos < 0) {
			return -1;
		}

		if (message[tag_tlv_pos + 2] == 0) {
			System.out.println("The reader reset");
		}
		return 0;
	}

	@Override
	public int NotifyReadTagBlock(byte[] message, int startIndex) {
		int curPos = 0;
		int paramLen = 0;
		int maxPos = 0;
		byte[] read_data = null;
		byte[] tag_data = null;

		paramLen = message[Message_Len_Start_Pos];
		paramLen = paramLen << 8;
		paramLen = paramLen + message[Message_Len_Start_Pos + 1];
		curPos = Message_Attr_Start_Pos;
		maxPos = curPos + paramLen;

		while (curPos < maxPos) {
			if (MRfidReader.eTlvAttrTagOperation == message[curPos]) {
				tag_data = new byte[message[curPos + 6] * 2];
				System.arraycopy(message, curPos + 7, tag_data, 0, tag_data.length);
			}
			curPos = curPos + message[curPos + 1] + 2;
		}

		if (null != tag_data) {
			System.out.print("Read Tag Block Data:");
			for (int iIndex = 0; iIndex < tag_data.length; iIndex++) {
				System.out.print(String.format("%02X ", tag_data[iIndex]));
			}
			System.out.println();
		} else {
			System.out.println("Fail to read tag block.");
		}
		return 0;
	}

	@Override
	public int NotifyWriteTagBlock(byte[] message, int startIndex) {
		int start_tlv_pos = startIndex + 8;
		int param_len = 0;
		int tag_tlv_pos = 0;
		int EPC_Tlv = 0;

		param_len = message[startIndex + 6] & 0xFF;
		param_len = param_len << 8;
		param_len = message[startIndex + 7] & 0xFF;

		tag_tlv_pos = GetTlvPosition(message, start_tlv_pos, param_len, MRfidReader.eTlvAttrStatus);
		if (tag_tlv_pos < 0) {
			return -1;
		}

		if (message[tag_tlv_pos + 2] == 0) {
			System.out.println("Success to write tag");
		}
		return 0;
	}

	@Override
	public int NotifyLockTag(byte[] message, int startIndex) {
		int start_tlv_pos = startIndex + 8;
		int param_len = 0;
		int tag_tlv_pos = 0;
		int EPC_Tlv = 0;

		param_len = message[startIndex + 6] & 0xFF;
		param_len = param_len << 8;
		param_len = message[startIndex + 7] & 0xFF;

		tag_tlv_pos = GetTlvPosition(message, start_tlv_pos, param_len, MRfidReader.eTlvAttrStatus);
		if (tag_tlv_pos < 0) {
			return -1;
		}

		if (message[tag_tlv_pos + 2] == 0) {
			System.out.println("Success to lock tag");
		}
		return 0;
	}

	@Override
	public int NotifyKillTag(byte[] message, int startIndex) {
		int start_tlv_pos = startIndex + 8;
		int param_len = 0;
		int tag_tlv_pos = 0;
		int EPC_Tlv = 0;

		param_len = message[startIndex + 6] & 0xFF;
		param_len = param_len << 8;
		param_len = message[startIndex + 7] & 0xFF;

		tag_tlv_pos = GetTlvPosition(message, start_tlv_pos, param_len, MRfidReader.eTlvAttrStatus);
		if (tag_tlv_pos < 0) {
			return -1;
		}

		if (message[tag_tlv_pos + 2] == 0) {
			System.out.println("success to kill tag");
		}
		return 0;
	}

	@Override
	public int NotifyInventoryOnce(byte[] message, int startIndex) {
		return 0;
	}
}
